package nl.sogyo.objectvisualisatie.core;

import java.util.ArrayList;
import java.util.TreeMap;

import nl.sogyo.objectvisualisatie.GUI.Observer;
import nl.sogyo.objectvisualisatie.data.MethodInfo;
import nl.sogyo.objectvisualisatie.data.ObjectInfo;
import nl.sogyo.objectvisualisatie.data.SourceCode;
import nl.sogyo.objectvisualisatie.trace.Trace;


/**
 * Model is the core of the application and the facade 
 * to the GUI-components.
 *  
 * @author Ben d'Hont
 */

public class Model {

	private Trace trace;
	private DataFacade dataFacade;
	
	private ArrayList<Observer> observerList;	// ArrayList with all GUI-components	
	private boolean autoposition = true;		// boolean for auto positioning the classes
	private Thread traceApp;					// Thread that starts another VM
	
	/*STILL HARDCODED WILL BE CHANGED SOON*/
	private String mainClass;//"example2.GUIMain";//"testapps.Testmain";//	// Main-klasse van het project dat wordt gemonitord
	private String classpath;//"-classpath C:\\Users\\Ben\\workspace\\Example\\bin";  // path waar de .class bestanden staan
	private String sourcepath;//"C:\\Users\\Ben\\workspace\\Example\\src\\example2\\"; // path waar de .java bestanden staan (broncode)

	/**
	 * Constructor
	 */
	public Model()
	{		
		observerList = new ArrayList<Observer>();
		dataFacade = new DataFacade(this);
		GUICreator guiCreator = new GUICreator();
		guiCreator.createGUIComponents(this);
	}
		
	/**
	 * Add an GUI-Component with superclass Observer to
	 * the list of all updateable components 
	 * @param obs = GUI-component with has superclass Observer
	 */
	public void attach(Observer obs){
		observerList.add(obs);
	}
	
	/**
	 * update all the views
	 */
	public void notifyObs(){
		for(Observer obs : observerList){
			obs.update();
		}
	}
	
	/**
	 * Start the trace application which start an VM
	 * and then the application that will be monitord
	 * The trace object will be started in een new tread
	 */
	public void startTrace()
	{
		trace = new Trace(dataFacade, classpath);
		//start a new thread to keep the GUI responding/refreshing
		traceApp = new Thread() {
			public void run() {
				String[] className = mainClass.split("\\."); 				// classname with package and class name
				String classNameOnly = className[(className.length-1)]; 	// classname without package and class name
				ObjectInfo objectInfo = new ObjectInfo(classNameOnly, 0);
				dataFacade.addObject(objectInfo);
				dataFacade.pushObjectStack(objectInfo);	
				
				String[] args = { mainClass };
				trace.startTrace(args);

					
			}
		};
		traceApp.start();
	}
	


	/**
	 * Set the autoposition of the GUI-canvas to true of false	
	 * @param bool = boolean true or false
	 */
	public void setAutoposition(Boolean bool)
	{
		autoposition = bool;
	}
	
	public Boolean getAutoposition()
	{
		return autoposition;
	}
	
	/* ***********************************
	 * Referable methods to the dataface class
	 * ***********************************/
	
	public String getSourcepath() {
		return sourcepath;
	}
	
	public ArrayList<MethodInfo> getMethodcalls()
	{
		return dataFacade.getMethodcalls();
	}
	
	public ArrayList<ObjectInfo> getobjectsList()
	{
		return dataFacade.getobjectsList();
	}
	
	public void removeAll()
	{
		dataFacade.removeAll();
	}
	
	public boolean isThreadContinue() {
		return dataFacade.isThreadContinue();
	}

	public void setThreadContinue(boolean bool) {
		dataFacade.setThreadContinue(bool);
	}
	
	public void setNext(boolean bool) {
		dataFacade.setNext(bool);	
	}
	public TreeMap<String, SourceCode> readAllSourcefiles()
	{		
		return dataFacade.readAllSourcefiles();
	}
	
	public void setMainClass(String mainClass) {
		this.mainClass = mainClass;
	}

	public void setClasspath(String classpath) {
		this.classpath = classpath;
	}

	public void setSourcepath(String sourcepath) {
		this.sourcepath = sourcepath;
	}
}
